TCP 与 UDP
Contents
TCP 数据段格式
传输层建立【端口 -> 端口】之间的通信,网络层建立【主机 -> 主机】之间的通信。
- 序列号:
TCP
把连接中发送到所有数据,按字节进行编号。当 SYN=1 时,序列号seq
就是报文段中第一个字节的数据编号。 - 确认号:是当前报文段的最后一个字节编号+1,也就是下一个报文段的序列号。确认号表示,已接受小于该确认号的所有数据。
- 窗口: 窗口大小是
TCP
接受缓冲区的剩余大小,用来进行流量控制
。发送方不能够发送超过对方窗口大小的数据,否则会被丢掉。
TCP 与 UDP 区别
TCP
是面向连接的;而UDP
是不需要建立连接,即发送数据之前不需要建立连接。
TCP
是可靠的,它保证数据的正确性;而UDP
是不可靠的,可能会丢包。
UDP
的实时性强,工作效率比TCP
高,适用于高速传输和实时性要求比较高的通信或者广播通信。
TCP
是点对点连接;UDP
支持多对多的交互通信。
TCP
对系统资源要求较高;UDP
对系统资源要求较少。
TCP 为什么是可靠连接?
TCP
都有一个发送缓冲区和一个接受缓冲区。
TCP
数据段里的序列号 Seq 能使TCP
保证按序到达
。TCP
数据段里的确认号 Ack 能使TCP
保证不丢包
,超时了会重传。TCP
拥有 流量控制 机制,TCP
数据段里还有一个2个字节的窗口
字段,它表示 接受缓冲区 里的剩余空间,发送方 根据这个窗口里的大小,发送比窗口小的数据量,否则发送的数据会被丢掉。这几点让TCP
能够保证可靠连接。
TCP
拥有 拥塞控制 机制。
UDP 为什么是不可靠的?
UDP
没有发送缓冲区,只有一个接受缓冲区。所以只要有数据就会发送,不管对方能不能接受。当对方的接受缓冲区满了之后,新来的数据就会被丢掉,UDP
是没有流量控制的,也没有确认号,所以UDP
是不可靠的。
TCP 三次握手
- 第一次握手:客户端将标识位 SYN 设置为 1,并且随机产生一个值 x,令
seq = x
,把报文段发送给服务端。
- 第二次握手:服务端看到 SYN = 1 就知道它是要请求建立连接,服务端把 SYN 和 ACK 都设置为 1,并且令
ack = x + 1
,随机生成一个值 y,令seq = y
,告诉对方它的序列号。
- 第三次握手:客服端收到数据段后检查 ACK 是否为 1,
ack == x + 1
?如果是,就把标志位 ACK 设置为 1,令ack = y + 1
,并且发送给服务端,服务端也做同样的判断后,如果正确,就说明连接建立成功。客户端与服务端之间可以开始传输数据了。
TCP 四次挥手
- 第一次挥手:客户端将标志位 FIN 设置为 1,用来断开与服务端的数据传输。
- 第二次挥手:服务端收到对方的关闭连接请求之后,发送一个确认号,确认号 ack 等于对方的序列号 seq + 1.
- 第三次挥手:同上。
- 第四次挥手:同上。
为什么建立连接是三次握手,而关闭连接是四次挥手?
因为三次握手
时,可以把标志位 SYN 和 ACK 放在同一个报文段
发送。
但关闭连接时,当收到对方的 FIN 通知时,它仅仅表示着对方已经没有数据发送了,但可能,我还有没把全部数据发送给对方。所以不能立马把 socket 连接关闭掉,等我把数据全部发送完之后,再发送 FIN 通知,如果收到对方的确认号了,就说明双方的连接都关闭了。所以在大多数情况下,FIN 和 ACK 报文段是分开发送的。
为什么不能用两次握手进行连接?
因为 两次握手 只能得到一方的确认,而TCP连接
就是为了,让双方彼此知道对方可以正确地接受数据了,并且协商双方的初始序列号。所以TCP连接
一定需要 三次握手,不能 两次握手。
为什么 TIME_WAIT 状态需要经过 2MSL 才能进入 CLOSED 状态?
因为在第四次挥手
时发送的 ACK 报文段可能在传输过程中丢失,如果服务端没有收到 ACK 就会重新发送 FIN 报文段。所以客户端至少要等一次发送和一次回复所需要的最大时间,也就是 2MSL.
MSL (Maximum Segment Lifetime):报文段在网络中的最长生存时间。